﻿using GN.Pay.Core.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Abp.Dependency;
using RabbitMQ.GNClient;
using RabbitMQ.GNClient.Events;
using static GN.Pay.Core.Consts.ServiceConstant;
using GN.Pay.Core.Services;
using GN.Pay.Core.Repositories;
using GN.Pay.TradeChannel;

namespace GN.Pay.Core.Tasks.Queue.Impl
{
    /// <summary>
    /// 
    /// </summary>
    class ClientTransfersConsumerQueue : AConsumerQueue<TradeTransfersApply>, IClientTransfersConsumerQueue
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="iocManager"></param>
        public ClientTransfersConsumerQueue(IIocManager iocManager)
            : base(QueueType.ClientTransfersApply, iocManager)
        {

        }

        /// <summary>
        /// 
        /// </summary>
        protected override ushort MaxPrefetchCount
        {
            get
            {
                return 10;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="eventConsumer"></param>
        /// <param name="data"></param>
        /// <param name="e"></param>
        /// <returns></returns>
        protected override async Task Consumer(IEventingConsumer eventConsumer, TradeTransfersApply data, DeliverEventArgs e)
        {
            await Task.Run(() =>
            {
                try
                {
                    TradeTransfersApply apply;
                    var result = Transfers(data.Id, out apply);
                    if (result == TradeApplyResultState.Balance_Insufficient_Error)
                    {
                        var queue = IocManager.Resolve<IQueueManager>();
                        var msg = new ObjectMessage(apply);
                        eventConsumer.Channel.Ack(e.DeliveryTag);
                        queue.Publish(QueueType.ClientTransfersApply, msg, new TimeSpan(0, 30, 0));
                        return;
                    }
                    if (result == TradeApplyResultState.Apply_Success_Wiat_Notify
                         || result == TradeApplyResultState.Complete_Success
                         || result == TradeApplyResultState.Info_Error)
                    {
                        eventConsumer.Channel.Ack(e.DeliveryTag);
                        return;
                    }
                    else
                    {
                        this.DelayConsumer(eventConsumer, apply, e, new TimeSpan(0, 0, 30));                       
                        return;
                    }
                }
                catch (Exception err)
                {
                    Logger.Error("回调队列异常:", err);
                    this.DelayConsumer(eventConsumer, data, e, new TimeSpan(0, 0, 30));                  
                    return;
                }
            });
        }

        private TradeApplyResultState Transfers(string id, out TradeTransfersApply apply)
        {
            var options = CreateUpdateUnitOfWorkOptions();
            using (var uow = UnitOfWorkManager.Begin(options))
            {
                var repository = IocManager.Resolve<ITradeTransfersApplyRepository>();
                apply = repository.Get(id);
                if (apply == null)
                {
                    return TradeApplyResultState.Complete_Success;
                }
                if (!IsTransfersState(apply))
                {
                    return TradeApplyResultState.Complete_Success;
                }
                var service = IocManager.Resolve<ITradeTransfersApplyService>();
                var result = service.Transfers(apply);
                uow.Complete();
                return result;
            }
        }

        private bool IsTransfersState(TradeTransfersApply apply)
        {
            return apply.ApplyState == TradeApplyState.Apply_Success
                 || apply.ApplyState == TradeApplyState.Execute_Error
                 || apply.ApplyState == TradeApplyState.Execute_Balance_Error;
        }
    }
}
